home *** CD-ROM | disk | FTP | other *** search
- /* HARDERR.C by Bill Buckels 1991 */
- /* written in LARGE MODEL MICROSOFT C 5.1 */
-
- /* This program demonstrates the use of a critical error management */
- /* Technique Quite Similar to C's own System Error Routines as defined */
- /* by the uniform standard in errno.h. */
-
- /* The Error Recovery and Reporting is implemented by a handler written */
- /* in assembly language. The reason for this is that the HARD ERRORs */
- /* are handled at a fairly low level and C doesn't really offer the */
- /* necessary control to implement this type of handler properly. */
-
- /* Bibliography : */
- /* The DOS Programmer's Reference 2nd Edition by Que Books provided the */
- /* necessary reference for both the DEVICE HEADER (page 339) and the */
- /* int 24h critical error handler (page 673). */
-
- /* My testing was less than thorough but all seems to work well enough */
- /* and this should give folks a template and a starting point at least. */
- /* I am not concerned with other compiler types since Microsoft C is the */
- /* Standard For Serious Developers. This will likely work with other */
- /* Mixed Language Environments Like Borland but I hardly felt like */
- /* Translating my work into a foreign tongue. However... */
-
- /* a possible substitution of MSC functions by TURBO C functions. */
- /* I am only guessing... there may be syntatical differences. */
- /* also the ASM module may have different rules imposed by TASM and */
- /* the ISR declaration may also have semantic differences, etc. */
-
- #ifdef TURBO
- #define _far far
- #define _dos_setvect setvect
- #define _dos_getvect getvect
- #define _disable disable
- #define _enable enable
- #define _exit exit
- #endif
-
- #include <stdio.h>
- #include <dos.h>
-
- #ifndef TRUE
- #define TRUE 1
- #endif
-
- #ifndef FALSE
- #define FALSE 0
- #endif
-
-
- /* a global structure for the hard error info. */
- /* theis structure is filled each time our int24 ISR is called */
- struct CRIT_ERROR{
- unsigned int HARDSTATUS;/* global status flag for Hard Errors */
- unsigned int HERRNO; /* global for the last error number */
- unsigned int DEVICE_SEG;/* global for the Driver Header Segment */
- unsigned int DEVICE_OFF;/* global for the Driver Header Offset */
- unsigned char IO_STATUS; /* a DISK I/O status flag */
- };
-
- struct CRIT_ERROR crit_error;
-
- /* a new interrupt handler for int 24h */
- /* written in assembly language and linked to as an external */
- extern interrupt _far int24(void);
-
- #ifndef MK_FP
- #define MK_FP(seg,off) ((char _far *)(((long)(seg) << 16) | (off)))
- #endif
-
-
- char *DEVICETEST[]={
- "\n\tTHIS IS A TEST OF THE CRITICAL ERROR HANDLER FOR DEVICE I/O.",
- "\tTHE PRINTER DEVICE (PRN) IS USED FOR THIS TEST.",
- "\tPLEASE MAKE SURE THAT THE PRINTER IS OFF-LINE.",
- "\tAND PRESS THE ENTER KEY TO START THE TEST OR ESCAPE TO ABORT.",
- NULL};
-
-
- char *DISKTEST[]={
- "\n\tTHIS IS A TEST OF THE CRITICAL ERROR HANDLER FOR DISK I/O.",
- "\tPLEASE MAKE SURE THAT THE DRIVE DOOR FOR DRIVE A: IS LEFT OPEN",
- "\tAND PRESS THE ENTER KEY TO START THE TEST OR ESCAPE TO ABORT.",
- NULL};
-
-
-
- main(int argc, char **argv)
- {
-
- FILE *fp;
- int i;
- char c;
-
- puts("\tHarderr by Bill Buckels 1991");
-
-
- _disable();
- /* replace the Hard Error Handler Vector with our own ISR. */
- /* when the program terminates this vector is restored */
- /* by the system termination handler. */
- _dos_setvect(0x24,int24);
- _enable();
-
- #define ENTERKEY '\x0d'
-
- /*--------------------| DISK I/O TEST |--------------------*/
-
- for (i=0; DISKTEST[i] != NULL; i++)puts(DISKTEST[i]);
-
- if((c=getch())==ENTERKEY) /* if enter is pressed do the test */
- {
- /* clear the previous hard error if any */
- hardclear();
- /* try to open an unlikely file on drive A: */
- /* if the Drive Door is Open theis will create a HARD ERROR */
- puts("\tNow accessing disk device drive A:");
- if((fp=fopen("A:\\$$$$$$$$.$$$","r"))==NULL)
- {
- hardperror();
- }
- else
- {
- fclose(fp);
- }
-
- }
-
- if(c=='\x00')c=getch(); /* clear function keys... */
-
-
- /*--------------------| DEVICE WRITE TEST |--------------------*/
-
- for (i=0; DEVICETEST[i] != NULL; i++)puts(DEVICETEST[i]);
-
- if((c=getch())==ENTERKEY) /* if enter is pressed do the test */
- {
- hardclear(); /* clear the previous error if any */
- puts("\tNow accessing logical device PRN.");
- if((fp=fopen("prn","w"))!=NULL)
- {
- while(!hardperror())fprintf(fp,"Turn The Printer Off.\n");
- fclose(fp);
- }
- else perror("\n\tSTD ERR RE: LOGICAL DEVICE PRN");
- }
-
- puts("\nhave a nice DOS!");
- _exit(0);
-
-
- }
-
- /* clear the Hard Error Status Flag */
- hardclear()
- {
- crit_error.HARDSTATUS=FALSE;
- }
-
-
- /* an array of hard error messages */
- char *harderrors[]={
-
- /* error code Meaning */
- /* (lower byte di) */
- /* 00H */ "Write Protect Error",
- /* 01H */ "Unknown Unit",
- /* 02H */ "Drive Not Ready",
- /* 03H */ "Unknown Command",
- /* 04H */ "Data Error (BAD CRC)",
- /* 05H */ "Bad Request Structure Length",
- /* 06H */ "Seek Error",
- /* 07H */ "Unknown Media Type",
- /* 08H */ "Sector Not Found",
- /* 09H */ "Printer Out Of Paper",
- /* 0AH */ "Write Fault",
- /* 0BH */ "Read Fault",
- /* 0CH */ "General Error"};
-
-
- /* a structure for a device header */
- struct DEVICE_HEADER{
- unsigned long nextdriver;
- unsigned int attribute;
- unsigned int strategy_routine;
- unsigned int interrupt_routine;
- unsigned char device_name[9];
- };
-
-
- /* if there has been a HARD error print the device error */
- hardperror()
- {
- char far *device_ptr;
- struct DEVICE_HEADER device_header;
- int i;
-
- if(crit_error.HARDSTATUS!=FALSE)
- {
-
- if(crit_error.IO_STATUS<128)
- {
- puts("\n\tHard Error Was Due To Disk I/O");
- if(crit_error.HERRNO<0 || crit_error.HERRNO > 0x0c)
- puts("\tUnknown Hard Error");
- else
- printf("\t%s\n",harderrors[crit_error.HERRNO]);
- }
- else
- {
- /* point to the header of the device that has failed */
- /* then print the device name to the screen. */
- device_ptr =MK_FP(crit_error.DEVICE_SEG,crit_error.DEVICE_OFF);
- memcpy(&device_header.nextdriver,device_ptr,
- sizeof(struct DEVICE_HEADER));
- /* replace whitespace with NULLs */
- for(i=0;i<8;i++)if(device_header.device_name[i] =='\x20')
- device_header.device_name[i] ='\x00';
- device_header.device_name[8] ='\x00';
- /* terminate ascii Z string */
- puts("\n\tHard Error Was not Due To DISK I/O.");
- printf("\tError was due to FAILURE of DEVICE %s.\n",
- device_header.device_name);
- }
- }
-
- return crit_error.HARDSTATUS;
-
- }